package com.zjhn.ds.task;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zjhn.ds.common.Constant;
import com.zjhn.ds.common.annotate.IgnoreTenant;
import com.zjhn.ds.domain.entity.jlw.Station;
import com.zjhn.ds.domain.entity.jlw.StationClassRecord;
import com.zjhn.ds.domain.entity.jlw.WorkshopClasses;
import com.zjhn.ds.domain.vo.EquipmentVo;
import com.zjhn.ds.domain.vo.StationDurationRecordVo;
import com.zjhn.ds.mapper.StationMapper;
import com.zjhn.ds.service.StationClassRecordService;
import com.zjhn.ds.utils.CommonUtil;
import com.zjhn.ds.utils.base.DateUtil;
import com.zjhn.ds.utils.base.RedisCache;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Scheduled;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @BelongsProject: ds_jlw
 * @BelongsPackage: com.zjhn.ds.task
 * @Author: sxt
 * @CreateTime: 2023-12-19  18:57
 * @Description:
 * @Version: 1.0
 */
@Slf4j
@Configuration
public class StationClassDurationStatisticTask {

    @Resource
    private CommonUtil commonUtil;

    @Resource
    private RedisCache redisCache;

    @Resource
    private StationMapper stationMapper;

    @Resource
    private StationClassRecordService stationClassRecordService;

    private final Object lock1 = new Object();
    private final Object lock2 = new Object();

    @IgnoreTenant
    @Scheduled(fixedDelay = 1000 * 60 * 5)
    public void statics() {
        long start = System.currentTimeMillis();
        log.info("====[INFO]====StationClassDurationStatisticTask====statics 机台班次时长统计定时任务触发");

        String workshopId = "523cd11213f4f82407b75880f941ee88";
        // 获取车间机台
        List<Station> stations = stationMapper.selectList(
                new QueryWrapper<Station>()
                        .eq("workshop_id", workshopId));

        // 获取当前班次
        WorkshopClasses currentClass = commonUtil.getWorkshopClasses();
        if (currentClass != null) {
            // 获取当天
            String currentDay = DateUtil.getCurrentDay(currentClass.getStartTime(), currentClass.getEndTime(), new Date());

            // 计算班次生产时间
            Integer betweenMinute = DateUtil.betweenMinute(currentClass.getStartTime(), currentClass.getEndTime());

            // 每批处理的数据量
            int batchSize = 50;

            // 数据分批
            List<List<Station>> batchList = new ArrayList<>();
            for (int i = 0; i < stations.size(); i += batchSize) {
                int endIndex = Math.min(i + batchSize, stations.size());
                List<Station> batch = stations.subList(i, endIndex);
                batchList.add(batch);
            }

            List<Thread> threadList = new ArrayList<>();
            for (List<Station> batch : batchList) {
                Thread thread = new Thread(() -> {
                    // 在这里编写处理子列表的逻辑
                    // 可以使用 for 循环遍历子列表中的数据，并进行相应的处理操作
                    List<String> stationIds = batch.stream()
                            .map(Station::getId)
                            .collect(Collectors.toList());

                    List<StationClassRecord> batchRecord = null;
                    synchronized (lock1) {
                        batchRecord = stationClassRecordService.list(
                                new QueryWrapper<StationClassRecord>()
                                        .in("station_id", stationIds)
                                        .eq("workshop_class_id", currentClass.getId())
                                        .eq("current_day", currentDay)
                        );
                    }

                    Map<String, StationClassRecord> recordMap = new HashMap<>();
                    if (batchRecord != null && batchRecord.size() > 0)
                        recordMap.putAll(batchRecord.stream().collect(Collectors.toMap(StationClassRecord::getStationId, c -> c)));

                    List<StationClassRecord> add = new ArrayList<>();
                    List<StationClassRecord> update = new ArrayList<>();
                    for (String stationId : stationIds) {
                        StationClassRecord stationClassRecord = recordMap.get(stationId);

                        StationDurationRecordVo stationDurationRecordVo = null;
                        Object durationRecord = redisCache.getCacheObject(Constant.REDIS_PRE.STATION_DURATION_RECORD + currentDay + ":" + currentClass.getId() + ":" + stationId);
                        if (durationRecord != null)
                            stationDurationRecordVo = JSONObject.parseObject(durationRecord.toString(), StationDurationRecordVo.class);

                        // 获取当前时间至 班次开始时间的 间隔分钟数
                        Integer between = DateUtil.betweenMinute(currentClass.getStartTime(), DateUtil.formatDateToString(new Date(), DateUtil.DATE_FORMAT_3));

                        Integer runTime = 0;
                        Integer idleTime = 0;
                        Integer faultTime = 0;
                        Integer stopTime = between;
                        if (stationDurationRecordVo != null) {
                            runTime = Integer.parseInt(stationDurationRecordVo.getRunTime());
                            idleTime = Integer.parseInt(stationDurationRecordVo.getIdleTime());
                            faultTime = Integer.parseInt(stationDurationRecordVo.getFaultTime());
                            stopTime = Integer.parseInt(stationDurationRecordVo.getStopTime());
                            if ((runTime + idleTime + faultTime + stopTime) != between)
                                // 防止时间总和不对
                                stopTime = between - runTime - idleTime - faultTime;
                        }

                        if (stationClassRecord == null) {
                            EquipmentVo equipment = commonUtil.getEquipmentById(commonUtil.getBindInfoById(stationId));
                            stationClassRecord = StationClassRecord.builder()
                                    .workshopId(workshopId)
                                    .workshopName(commonUtil.getWorkshopById(workshopId))
                                    .workshopClassId(currentClass.getId())
                                    .workshopClassName(currentClass.getName())
                                    .stationId(stationId)
                                    .stationCode(commonUtil.getStationById(stationId).getStationCode())
                                    .equipmentId(equipment.getId())
                                    .equipmentName(equipment.getEquipmentName())
                                    .currentDay(currentDay)
                                    .produceTime(betweenMinute)
                                    .runTime(runTime)
                                    .idleTime(idleTime)
                                    .faultTime(faultTime)
                                    .stopTime(stopTime)
                                    .oee(BigDecimal.ZERO)
                                    .build();
                            add.add(stationClassRecord);
                        } else {
                            stationClassRecord.setRunTime(runTime);
                            stationClassRecord.setIdleTime(idleTime);
                            stationClassRecord.setFaultTime(faultTime);
                            stationClassRecord.setStopTime(stopTime);
                            update.add(stationClassRecord);
                        }

                        // 计算稼动率
                        if (stationClassRecord.getRunTime() != 0 && between != 0) {
                            // 稼动率 = （正常运行时间 + 断网时间） / 运行时长
                            BigDecimal oee = BigDecimal.valueOf(stationClassRecord.getRunTime() + stationClassRecord.getStopTime())
                                    .divide(BigDecimal.valueOf(between), 3, RoundingMode.HALF_UP)
                                    .multiply(BigDecimal.valueOf(100));
                            stationClassRecord.setOee(oee);
                        }
                    }

                    synchronized (lock2) {
                        if (add.size() > 0)
                            stationClassRecordService.saveBatch(add);
                        if (update.size() > 0)
                            stationClassRecordService.updateBatchById(update);
                    }

                });

                thread.start();
                threadList.add(thread);
            }

            for (Thread thread : threadList) {
                try {
                    thread.join();
                } catch (InterruptedException e) {
                    log.error("====[ERROR]====StationClassDurationStatisticTask====statics 线程异常 e:{}", e.getMessage());
                }
            }

        }
        long end = System.currentTimeMillis();
        log.info("====[INFO]====StationClassDurationStatisticTask====statics 机台班次时长统计定时任务结束 time:{}ms", end - start);
    }

}
